package block_example

import (
	"bytes"
	"crypto/sha256"
	"strconv"
	"time"
)

// 区块结构
type Block struct {
	Timestamp int64  // 时间戳
	Data      []byte // 当前区块信息
	PrevHash  []byte // 上一个区块(前区块 Hash) Hash
	Hash      []byte // 当前区块 Hash
}

// 生成当前区块 Hash
func (this *Block) SetHash() {

	// 进行加密拼接 PrevHash + Date + Timestamp ---> Hash

	// 将时间戳由整型 转 二进制
	timestamp := []byte(strconv.FormatInt(this.Timestamp, 10))

	// 将三个二进制进行拼接
	headers := bytes.Join(
		[][]byte{this.PrevHash, this.Data, timestamp},
		[]byte{},
	)

	// 将拼接之后的 headers 进行 SHA256 加密
	hashs := sha256.Sum256(headers)

	this.Hash = hashs[:]
}

// 新建区块
// date
// prev_block_hash 前区块 Hash
func NewBlock(data string, prev_block_hash []byte) *Block {

	block := new(Block)
	block.Timestamp = time.Now().Unix()
	block.Data = []byte(data)
	block.PrevHash = prev_block_hash

	block.SetHash()

	return block
}

// 新建一个创世块
func NewGenesisBlock() *Block {
	genesis := new(Block)
	genesis.Data = []byte("Genesis block")
	genesis.PrevHash = []byte{}

	return genesis
}

// 区块链结构
type BlockChain struct {
	Blocks []*Block
}

// 添加区块
func (this *BlockChain) AddBlock(data string) {

	// 得到 新添加区块的 前区块(最后一个)
	prevBlock := this.Blocks[len(this.Blocks)-1]
	// 根据 data 创建一个新的区块
	newBlock := NewBlock(data, prevBlock.Hash)
	// 添加到区块链中
	this.Blocks = append(this.Blocks, newBlock)
}

// 新建区块链
func NewBlockChain() *BlockChain {

	blockChain := new(BlockChain)
	blockChain.Blocks = []*Block{NewGenesisBlock()}

	return blockChain
}

